package com.ldy.biz.shop.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request.Amount;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request.Payer;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.ldy.biz.ShopConst;
import com.ldy.biz.shop.entity.Order;
import com.ldy.biz.shop.entity.OrderItem;
import com.ldy.biz.shop.entity.Product;
import com.ldy.biz.shop.mapper.ProductMapper;
import com.ldy.biz.shop.service.OrderItemService;
import com.ldy.biz.shop.service.OrderService;
import com.ldy.biz.shop.service.ProductService;
import com.ldy.core.util.SequenceUtil;

@Service
@Transactional
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {

	private static final Logger logger = LoggerFactory.getLogger(ProductServiceImpl.class);
	@Autowired
	private OrderItemService orderItemService;

	@Autowired
	private OrderService orderService;

	@Autowired
	private WxPayService wxPayService;

	@Override
	public synchronized Order createOrder(Order order) {
		List<OrderItem> items = order.getItems();
		String orderNo = SequenceUtil.get("OrderNo");
		order.setOrderId(orderNo);
		Date now = new Date();
		order.setCreateTime(now);
		order.setLastUpdateTime(now);
		order.setOrderTime(now);
		List<Product> products = new ArrayList<Product>();
		// 获取商品，判断是否有库存
		if (!CollectionUtils.isEmpty(items)) {
			items.forEach(c -> {
				c.setOrderId(orderNo);
				Product product = getById(c.getProductId());
				Assert.notNull(product, "无效商品");
				Assert.isTrue(product.getStatus() == 1, "无效商品");
				Assert.isTrue(product.getPrice().compareTo(c.getUnitPrice()) == 0, "商品价格不正确");

				Integer stockQuantity = product.getStockQuantity();
				if (stockQuantity != null) {
					Assert.isTrue(stockQuantity >= c.getQuantity(), "商品[" + product.getName() + "]库存数量不够");
					product.setStockQuantity(product.getStockQuantity() - c.getQuantity());
					products.add(product);
				}
			});
			orderItemService.saveBatch(items);
		}
		order.setStatus(ShopConst.OrderStatus.待付款.name());
		if (!CollectionUtils.isEmpty(products)) {
			updateBatchById(products);
		}
		try {
			// 生成支付订单
			WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
			request.setOutTradeNo(orderNo);
			request.setDescription(String.format("%s的%s订单", order.getOrderPerson(), order.getOrderType()));
			Amount amount = new Amount();
			amount.setTotal(order.getTotalAmount().movePointRight(2).intValueExact()); // 分
			request.setAmount(amount);
			Payer payer = new Payer();
			payer.setOpenid(order.getCustomerId());
			request.setPayer(payer);
			WxPayUnifiedOrderV3Result.JsapiResult prePay = wxPayService.createOrderV3(TradeTypeEnum.JSAPI, request);
			order.setPrePay(prePay);
			order.setPrepayId(prePay.getPackageValue());
		} catch (Exception e) {
			logger.error("", e);
			order.setStatus(ShopConst.OrderStatus.支付异常.name());
		}
		orderService.save(order);
		return order;

	}

	@Override
	public void orderPay(String orderId) {
		Order order = orderService.getById(orderId);
		Assert.notNull(order, "无效订单");
		if (ShopConst.OrderStatus.待付款.name().equals(order.getStatus())) {
			try {
				WxPayOrderQueryV3Result result = wxPayService.queryOrderV3(null, orderId);
				Assert.isTrue("SUCCESS".equals(result.getTradeState()), "商品未支付");
				order.setStatus(ShopConst.OrderStatus.已付款.name());
				orderService.updateById(order);
			} catch (WxPayException e) {
				logger.error("", e);
				throw new IllegalArgumentException("支付查询异常" + e.getMessage());
			}
		}
	}

	@Override
	public void orderCancel(String orderId) {
		Order order = orderService.getById(orderId);
		Assert.notNull(order, "无效订单");
		if (ShopConst.OrderStatus.待付款.name().equals(order.getStatus())
				|| ShopConst.OrderStatus.支付异常.name().equals(order.getStatus())) {
			order.setStatus(ShopConst.OrderStatus.已取消.name());
			orderService.updateById(order);
			QueryWrapper<OrderItem> queryWrapper = new QueryWrapper<OrderItem>();
			queryWrapper.eq("order_id", orderId);
			List<OrderItem> list = orderItemService.list(queryWrapper);
			for (OrderItem item : list) {
				Product product = getById(item.getProductId());
				product.setStockQuantity(product.getStockQuantity() + item.getQuantity());
				updateById(product);
			}
		}
	}

}
